//-------------------------------------------------------------------
//	Copyright (c) 2010-2014  Zhirnov Andrey
//	This file is part of the "UX Standard Lib" project.
//	See copyright notice in "UX_STL_Core.h".
//-------------------------------------------------------------------

#ifndef _UXS_DIMENSIONS_HELPERS_H
#define _UXS_DIMENSIONS_HELPERS_H

#pragma once

#include "../BaseTypes/Types.h"

namespace UX_STL
{
namespace UXTypes
{


#	define _UX_DIM_OPERATORS_SELF( _op, _value ) \
		\
		Self& operator _op##= (const Self &right)			{ _value _op##= right._value;  return *this; } \
		Self  operator _op    (const Self &right)	const	{ return Self( _value _op right._value ); }
		

#	define _UX_DIM_OPERATORS_TYPE( _op, _value, _type, _member_opt ) \
		\
		Self& operator _op##= (const _type &right)						{ _value _op##= (value_t) right _member_opt;  return *this; } \
		Self  operator _op    (const _type &right)	const				{ return Self( _value _op (value_t) right _member_opt ); } \
		\
		friend Self operator _op (const _type &left, const Self &right)	{ return Self( (value_t) left _member_opt _op right._value ); }


#	define _UX_DIM_OPERATORS_TEMPLATE( _op, _value, _member_opt ) \
		\
		template <typename _A_> Self& operator _op##= (const _A_ &right)		{ _value _op##= (value_t) right _member_opt;  return *this; } \
		template <typename _A_> Self  operator _op    (const _A_ &right) const	{ return Self( _value _op (value_t) right _member_opt ); } \
		\
		friend template <typename _A_> \
		Self operator _op (const _A_ &left, const Self &right)	{ return Self( (value_t) left _member_opt _op right._value ); }


#	define _UX_DIM_CMP_OPERATORS_SELF( _value ) \
		\
		bool operator == (const Self &right)	const		{ return this->_value == right._value; } \
		bool operator != (const Self &right)	const		{ return this->_value != right._value; } \
		bool operator >  (const Self &right)	const		{ return this->_value >  right._value; } \
		bool operator <  (const Self &right)	const		{ return this->_value <  right._value; } \
		bool operator >= (const Self &right)	const		{ return this->_value >= right._value; } \
		bool operator <= (const Self &right)	const		{ return this->_value <= right._value; }
	

#	define _UX_DIM_CMP_OPERATORS_TYPE( _value, _type, _member_opt ) \
		\
		bool operator == (const _type &right)	const		{ return this->_value == (value_t)( right _member_opt ); } \
		bool operator != (const _type &right)	const		{ return this->_value != (value_t)( right _member_opt ); } \
		bool operator >  (const _type &right)	const		{ return this->_value >  (value_t)( right _member_opt ); } \
		bool operator <  (const _type &right)	const		{ return this->_value <  (value_t)( right _member_opt ); } \
		bool operator >= (const _type &right)	const		{ return this->_value >= (value_t)( right _member_opt ); } \
		bool operator <= (const _type &right)	const		{ return this->_value <= (value_t)( right _member_opt ); } \
		\
		friend bool operator == (const _type &left, const Self &right)	{ return (value_t)( left _member_opt ) == right._value; } \
		friend bool operator != (const _type &left, const Self &right)	{ return (value_t)( left _member_opt ) != right._value; } \
		friend bool operator >  (const _type &left, const Self &right)	{ return (value_t)( left _member_opt ) >  right._value; } \
		friend bool operator <  (const _type &left, const Self &right)	{ return (value_t)( left _member_opt ) <  right._value; } \
		friend bool operator >= (const _type &left, const Self &right)	{ return (value_t)( left _member_opt ) >= right._value; } \
		friend bool operator <= (const _type &left, const Self &right)	{ return (value_t)( left _member_opt ) <= right._value; }
	

#	define _UX_DIM_CMP_OPERATORS_TEMPLATE( _value, _member_opt ) \
		\
		template <typename _A_> bool operator == (const _A_ &right) const	{ return this->_value == (value_t)( right _member_opt ); } \
		template <typename _A_> bool operator != (const _A_ &right) const	{ return this->_value != (value_t)( right _member_opt ); } \
		template <typename _A_> bool operator >  (const _A_ &right) const	{ return this->_value >  (value_t)( right _member_opt ); } \
		template <typename _A_> bool operator <  (const _A_ &right) const	{ return this->_value <  (value_t)( right _member_opt ); } \
		template <typename _A_> bool operator >= (const _A_ &right) const	{ return this->_value >= (value_t)( right _member_opt ); } \
		template <typename _A_> bool operator <= (const _A_ &right) const	{ return this->_value <= (value_t)( right _member_opt ); } \
		\
		template <typename _A_> friend bool operator == (const _A_ &left, const Self &right)	{ return (value_t)( left _member_opt ) == right._value; } \
		template <typename _A_> friend bool operator != (const _A_ &left, const Self &right)	{ return (value_t)( left _member_opt ) != right._value; } \
		template <typename _A_> friend bool operator >  (const _A_ &left, const Self &right)	{ return (value_t)( left _member_opt ) >  right._value; } \
		template <typename _A_> friend bool operator <  (const _A_ &left, const Self &right)	{ return (value_t)( left _member_opt ) <  right._value; } \
		template <typename _A_> friend bool operator >= (const _A_ &left, const Self &right)	{ return (value_t)( left _member_opt ) >= right._value; } \
		template <typename _A_> friend bool operator <= (const _A_ &left, const Self &right)	{ return (value_t)( left _member_opt ) <= right._value; }
		

#	define _UX_DIM_ALL_INTEGER_OPERATORS_SELF( _value ) \
		_UX_DIM_OPERATORS_SELF( +,	_value ) \
		_UX_DIM_OPERATORS_SELF( -,	_value ) \
		_UX_DIM_OPERATORS_SELF( *,	_value ) \
		_UX_DIM_OPERATORS_SELF( /,	_value ) \
		_UX_DIM_OPERATORS_SELF( %,	_value ) \
		_UX_DIM_OPERATORS_SELF( >>,	_value ) \
		_UX_DIM_OPERATORS_SELF( <<,	_value ) \
		_UX_DIM_OPERATORS_SELF( |,	_value ) \
		_UX_DIM_OPERATORS_SELF( &,	_value ) \
		_UX_DIM_OPERATORS_SELF( ^,	_value ) \
		_UX_DIM_CMP_OPERATORS_SELF( _value ) \
		Self	operator ! () const		{ return Self( not _value ); } \
		Self	operator ~ () const		{ return Self( ~_value ); } \
		/*Self	operator - () const		{ return Self( -_value ); }  /* not available for unsigned types */ \
		Self &		operator ++ ()		{ ++_value;  return *this; } \
		Self &		operator -- ()		{ --_value;  return *this; } \
		const Self	operator ++ (int)	{ Self	ret(*this);  ++(*this);  return ret; } \
		const Self	operator -- (int)	{ Self	ret(*this);  --(*this);  return ret; }
	

#	define _UX_DIM_ALL_INTEGER_OPERATORS_TYPE( _value, _type, _member_opt ) \
		_UX_DIM_OPERATORS_TYPE( +,	_value,	_type, ) \
		_UX_DIM_OPERATORS_TYPE( -,	_value,	_type, ) \
		_UX_DIM_OPERATORS_TYPE( *,	_value,	_type, ) \
		_UX_DIM_OPERATORS_TYPE( /,	_value,	_type, ) \
		_UX_DIM_OPERATORS_TYPE( %,	_value,	_type, ) \
		_UX_DIM_OPERATORS_TYPE( >>,	_value,	_type, ) \
		_UX_DIM_OPERATORS_TYPE( <<,	_value,	_type, ) \
		_UX_DIM_OPERATORS_TYPE( |,	_value,	_type, ) \
		_UX_DIM_OPERATORS_TYPE( &,	_value,	_type, ) \
		_UX_DIM_OPERATORS_TYPE( ^,	_value,	_type, ) \
		_UX_DIM_CMP_OPERATORS_TYPE(	_value, _type, ) 


#	define _UX_DIM_ALL_INTEGER_OPERATORS_TEMPLATE( _value, _member_opt ) \
		_UX_DIM_OPERATORS_TEMPLATE( +,	_value,	_member_opt ) \
		_UX_DIM_OPERATORS_TEMPLATE( -,	_value,	_member_opt ) \
		_UX_DIM_OPERATORS_TEMPLATE( *,	_value,	_member_opt ) \
		_UX_DIM_OPERATORS_TEMPLATE( /,	_value,	_member_opt ) \
		_UX_DIM_OPERATORS_TEMPLATE( %,	_value,	_member_opt ) \
		_UX_DIM_OPERATORS_TEMPLATE( >>,	_value,	_member_opt ) \
		_UX_DIM_OPERATORS_TEMPLATE( <<,	_value,	_member_opt ) \
		_UX_DIM_OPERATORS_TEMPLATE( |,	_value,	_member_opt ) \
		_UX_DIM_OPERATORS_TEMPLATE( &,	_value,	_member_opt ) \
		_UX_DIM_OPERATORS_TEMPLATE( ^,	_value,	_member_opt ) \
		_UX_DIM_CMP_OPERATORS_TEMPLATE(	_value, _member_opt ) 


#	define _UX_DIM_ALL_FLOAT_OPERATORS_SELF( _value ) \
		_UX_DIM_OPERATORS_SELF( +,	_value ) \
		_UX_DIM_OPERATORS_SELF( -,	_value ) \
		_UX_DIM_OPERATORS_SELF( *,	_value ) \
		_UX_DIM_OPERATORS_SELF( /,	_value ) \
		_UX_DIM_CMP_OPERATORS_SELF( _value ) \
		Self	operator - () const		{ return Self( -_value ); } \
		Self &		operator ++ ()		{ ++_value;  return *this; } \
		Self &		operator -- ()		{ --_value;  return *this; } \
		const Self	operator ++ (int)	{ Self	ret(*this);  ++(*this);  return ret; } \
		const Self	operator -- (int)	{ Self	ret(*this);  --(*this);  return ret; }
	

#	define _UX_DIM_ALL_FLOAT_OPERATORS_TYPE( _value, _type, _member_opt ) \
		_UX_DIM_OPERATORS_TYPE( +,	_value,	_type, ) \
		_UX_DIM_OPERATORS_TYPE( -,	_value,	_type, ) \
		_UX_DIM_OPERATORS_TYPE( *,	_value,	_type, ) \
		_UX_DIM_OPERATORS_TYPE( /,	_value,	_type, ) \
		_UX_DIM_CMP_OPERATORS_TYPE(	_value, _type, ) 


#	define _UX_DIM_ALL_FLOAT_OPERATORS_TEMPLATE( _value, _type, _member_opt ) \
		_UX_DIM_OPERATORS_TEMPLATE( +,	_value,	_type, ) \
		_UX_DIM_OPERATORS_TEMPLATE( -,	_value,	_type, ) \
		_UX_DIM_OPERATORS_TEMPLATE( *,	_value,	_type, ) \
		_UX_DIM_OPERATORS_TEMPLATE( /,	_value,	_type, ) \
		_UX_DIM_CMP_OPERATORS_TEMPLATE(	_value, _type, ) 


}	// UXTypes
}	// UX_STL

#endif	// _UXS_DIMENSIONS_HELPERS_H